home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
b
/
b.lha
/
B
/
src
/
bed
/
goto.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-24
|
5KB
|
318 lines
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
static char rcsid[] = "$Header: goto.c,v 2.4 85/08/22 16:03:06 timo Exp $";
/*
* B editor -- Random access focus positioning.
*/
#include "b.h"
#include "feat.h"
#include "erro.h"
#include "node.h"
#include "gram.h"
#include "supr.h"
extern int winheight;
extern int winstart;
#define BEFORE (-1)
#define INSIDE 0
#define BEYOND 1
/*
* Random cursor positioning (e.g., with a mouse).
*/
Visible bool
gotocursor(ep)
environ *ep;
{
int y;
int x;
if (!sense(&y, &x))
return No;
#ifdef SCROLLBAR
if (y == winheight)
return gotoscrollbar(ep, y, x);
#endif SCROLLBAR
if (!backtranslate(&y, &x))
return No;
if (!gotoyx(ep, y, x))
return No;
gotofix(ep, y, x);
return Yes;
}
#ifdef SCROLLBAR
/*
* Special case for goto: user pointed at some point in the scroll bar.
* Go directly to the corresponding line.
* (The scroll bar is only present when winstart == 0; it extends from
* col 0 to winheight-1 inclusive.)
*/
Hidden bool
gotoscrollbar(ep, y, x)
environ *ep;
int y;
int x;
{
int w;
if (winstart != 0 || x >= winheight) { /* Not within scroll bar */
error(GOTO_OUT);
return No;
}
top(&ep->focus);
ep->mode = WHOLE;
higher(ep);
w = width(tree(ep->focus));
if (w >= 0)
w = 1;
else
w = 1-w;
if (!gotoyx(ep, x * w / winheight, 0))
return No;
oneline(ep);
return Yes;
}
#endif SCROLLBAR
/*
* Set the focus to the smallest node or subset surrounding
* the position (y, x).
*/
Visible bool
gotoyx(ep, y, x)
register environ *ep;
register int y;
register int x;
{
register node n;
register string *rp;
register int i;
register int pc;
ep->mode = WHOLE;
while ((pc = poscomp(ep->focus, y, x)) != INSIDE) {
if (!up(&ep->focus)) {
if (pc == BEFORE)
ep->mode = ATBEGIN;
else
ep->mode = ATEND;
higher(ep);
return No;
}
}
higher(ep);
for (;;) {
switch (poscomp(ep->focus, y, x)) {
case BEFORE:
i = ichild(ep->focus);
n = tree(parent(ep->focus)); /* Parent's !!! */
rp = noderepr(n);
if (Fw_positive(rp[i-1])) {
s_up(ep);
ep->s1 = ep->s2 = 2*i - 1;
ep->mode = SUBSET;
}
else if (left(&ep->focus))
ep->mode = ATEND;
else
ep->mode = ATBEGIN;
return Yes;
case INSIDE:
n = tree(ep->focus);
if (nchildren(n) >= 1 && Type(firstchild(n)) != Tex) {
s_down(ep);
continue;
}
ep->mode = WHOLE;
return Yes;
case BEYOND:
if (rite(&ep->focus))
continue;
n = tree(parent(ep->focus)); /* Parent's !!! */
rp = noderepr(n);
i = ichild(ep->focus);
if (Fw_positive(rp[i])) {
s_up(ep);
ep->s1 = ep->s2 = 2*i + 1;
ep->mode = SUBSET;
}
else
ep->mode = ATEND;
return Yes;
default:
Abort();
/* NOTREACHED */
}
}
}
/*
* Deliver relative position of (y, x) with respect to focus p:
* BEFORE: (y, x) precedes focus;
* INSIDE: (y, x) contained in focus;
* EAFTER: (y, x) follows focus.
*/
Hidden int
poscomp(p, y, x)
register path p;
register int y;
register int x;
{
register int ly;
register int lx;
register int w;
register string *rp;
register node n;
ly = Ycoord(p);
lx = Xcoord(p);
if (y < ly || y == ly && (lx < 0 || x < lx))
return BEFORE;
n = tree(p);
w = width(n);
if (w < 0) {
if (y == ly) { /* Hack for position beyond end of previous line */
rp = noderepr(n);
if (Fw_negative(rp[0]))
return BEFORE;
}
ly += -w;
lx = -1;
}
else {
if (lx >= 0)
lx += w;
}
if (y < ly || y == ly && (lx < 0 || x < lx))
return INSIDE;
return BEYOND;
}
/*
* Position focus exactly at character indicated by (y, x) if possible.
* If this is the start of something larger, position focus at largest
* object starting here.
*/
Visible Procedure
gotofix(ep, y, x)
environ *ep;
int y;
int x;
{
int fx;
int fy;
int len;
string repr;
switch (ep->mode) {
case ATBEGIN:
case ATEND:
return; /* No change; the mouse pointed in the margin. */
case SUBSET:
if (ep->s1 > 1) {
fx = Xcoord(ep->focus);
fy = Ycoord(ep->focus);
len = focoffset(ep);
if (len < 0 || fy != y)
return;
if ((ep->s1&1) && fx + len >= x-1) {
repr = noderepr(tree(ep->focus))[ep->s1/2];
if ((repr && repr[0] == ' ') != (fx + len == x))
return;
}
else if (fx + len == x)
return;
}
ep->mode = WHOLE;
/* Fall through */
case WHOLE:
fx = Xcoord(ep->focus);
fy = Ycoord(ep->focus);
if (y != fy)
return;
if (x <= fx ) {
for (;;) {
if (ichild(ep->focus) > 1)
break;
if (!up(&ep->focus))
break;
repr = noderepr(tree(ep->focus))[0];
if (!Fw_zero(repr)) {
s_down(ep);
break;
}
higher(ep);
}
if (issublist(symbol(tree(ep->focus))))
fixsublist(ep);
return;
}
fixfocus(ep, x - fx);
ritevhole(ep);
switch(ep->mode) {
case VHOLE:
len = width(tree(ep->focus));
break;
case FHOLE:
len = fwidth(noderepr(tree(ep->focus))[ep->s1/2]);
break;
default:
return;
}
if (ep->s2 < len) {
ep->mode = SUBRANGE;
ep->s3 = ep->s2;
}
return;
default:
Abort();
}
}
/*
* Refinement for gotoyx -- don't show right sublist of something.
*/
Hidden Procedure
fixsublist(ep)
environ *ep;
{
path pa = parent(ep->focus);
node n;
if (!pa)
return;
n = tree(pa);
if (nchildren(n) > ichild(ep->focus))
return;
if (samelevel(symbol(n), symbol(tree(ep->focus)))) {
ep->mode = SUBLIST;
ep->s3 = 1;
}
}